<?php

declare(strict_types=1);

namespace app\model\usr;

use think\Model;
use app\eslib\EsUtils;
use app\model\admin\LoginState;
use think\facade\Cache;
use think\facade\Db;

/**
 * 用户模型类
 * @version 1.0.0
 */
class UsersModel extends Model
{
    // 设置当前模型对应的完整数据表名称
    protected $table = 'usr_users';

    // 数据表名称常量
    const TABLE_NAME = 'usr_users';

    // 开启自动时间戳（默认为整型int）
    protected $autoWriteTimestamp = true;

    // 定义时间戳字段名
    protected $createTime = 'created_at';
    protected $updateTime = 'updated_at';

    /**
     * 返回 性别 访问器的数据
     * @return array
     */
    public function getGenderDataAttr(): array
    {
        return [
            ['text' => '未知', 'value' => 0],
            ['text' => '男', 'value' => 1],
            ['text' => '女', 'value' => 2],
        ];
    }

    /**
     * 返回 性别 访问器的值
     * @return string
     */
    public function getGenderTextAttr($value, $data)
    {
        $value = $data['gender'];
        if (is_numeric($value)) {
            $value = intval($value);
        }
        $data = (array) $this->getGenderDataAttr();
        $result = array_filter($data, function ($v) use ($value) {
            return $v['value'] == $value;
        }, ARRAY_FILTER_USE_BOTH);
        return $result ? current($result)['text'] : $value;
    }
    /**
     * 返回 状态 访问器的数据
     * @return array
     */
    public function getStatusDataAttr(): array
    {
        return [
            ['text' => '正常', 'value' => 0],
            ['text' => '禁止', 'value' => 1],
        ];
    }

    /**
     * 返回 状态 访问器的值
     * @return string
     */
    public function getStatusTextAttr($value, $data)
    {
        $value = $data['status'];
        if (is_numeric($value)) {
            $value = intval($value);
        }
        $data = (array) $this->getStatusDataAttr();
        $result = array_filter($data, function ($v) use ($value) {
            return $v['value'] == $value;
        }, ARRAY_FILTER_USE_BOTH);
        return $result ? current($result)['text'] : $value;
    }
    /**
     * 返回 是否虚拟用户 访问器的数据
     * @return array
     */
    public function getIsBogusDataAttr(): array
    {
        return [
            ['text' => '是', 'value' => 0],
            ['text' => '否', 'value' => 1],
        ];
    }

    /**
     * 返回 是否虚拟用户 访问器的值
     * @return string
     */
    public function getIsBogusTextAttr($value, $data)
    {
        $value = $data['is_bogus'];
        if (is_numeric($value)) {
            $value = intval($value);
        }
        $data = (array) $this->getIsBogusDataAttr();
        $result = array_filter($data, function ($v) use ($value) {
            return $v['value'] == $value;
        }, ARRAY_FILTER_USE_BOTH);
        return $result ? current($result)['text'] : $value;
    }

    /**
     * 使用视图查询
     */
    public function scopeDbView($query)
    {
        return $query->table('v_yx_users');
    }

    /**
     * 复制指定的记录
     */
    public static function copy($id)
    {
        $data = self::find($id)->toArray();
        $data['xxx_name'] .= ' - 副本';
        unset($data['id']);
        unset($data['created_at']);
        unset($data['updated_at']);
        try {
            $model = self::create($data);
            return EsUtils::stdMessage(true, '', $model->id);
        } catch (\PDOException $ex) {
            return EsUtils::stdMessage(false, $ex->getMessage());
        }
    }
    /**
     * 登录、注册、更新用户账号
     * openid 长度28
     */
    public static function doLogin($data)
    {
        if (empty($data['openid'])) {
            return EsUtils::stdMessage(false, 'openid是必填项目', $data);
        }
        $openid = $data['openid'];
        $inviterId = isset($data['vid']) ? intval($data['vid']) : 0; // 邀请人ID
        $classRoomId = isset($data['roomid']) ? intval($data['roomid']) : 0; // 班级ID
        $initHP = 5000; // 账号初始化默认能量值
        // 字段过滤
        $filterMap = ['nick_name' => 'nickName', 'avatar' => 'avatarUrl', 'gender' => 'gender', 'mobile' => 'mobile'];
        $postData = [];
        foreach ($filterMap as $colName => $inputName) {
            if (isset($data[$inputName]) && strlen(trim(strval($data[$inputName]))) > 0) {
                $postData[$colName] = $data[$inputName];
            }
        }
        if ($inviterId > 0) {
            $postData['inviter_id'] = $inviterId;
        }
        $returnFields = ['id', 'nick_name', 'avatar', 'gender', 'health_point', 'integral', 'inviter_id'];
        Db::startTrans();
        try {
            // 查询账号，只返回必要的数据
            $model = Db::table(self::TABLE_NAME)->where('wx_openid', $openid)->field($returnFields)->find();
            if (!$model) {
                // 创建账号
                $postData['wx_openid'] = $openid;
                $postData['user_name'] = $openid;
                $postData['health_point'] = $initHP;
                $postData['created_at'] = time();
                $userId = Db::table(self::TABLE_NAME)->insertGetId($postData);
                if ($userId && $inviterId) {
                    // 邀请增加能量值
                    Db::table(self::TABLE_NAME)->where('id', $inviterId)->inc('health_point', 1000)->update();
                }
            } else {
                $userId = $model['id'];
                if ($model['inviter_id'] && isset($postData['inviter_id'])) {
                    // 邀请人只允许绑定一次，绑定过就不能更改了
                    unset($postData['inviter_id']);
                }
                if ($postData) {
                    // 更新账号
                    $postData['updated_at'] = time();
                    Db::table(self::TABLE_NAME)->where('id', $userId)->update($postData);
                }
            }
            if ($userId && $classRoomId) {
                // 加入班级
                YxClassroom2studentModel::createRecord($userId, $classRoomId);
            }
            $token = LoginState::getJwt($userId, 'api'); // 生成 token
            $model['token'] = $token;
            // 提交事务
            Db::commit();
            return EsUtils::stdMessage(true, '', $model);
        } catch (\PDOException $ex) {
            // 回滚事务
            Db::rollback();
            return EsUtils::stdMessage(false, $ex->getMessage());
        }
    }

    /**
     * 汇总统计
     * 不应该直接从日志表汇总，数据量太大了。
     * 应该做每日报表，每日统计，然后再从每次报表汇总。
     * 统计字段是否要单独出来一张表？
     */
    public function doStatistical()
    {
        // update yx_users set health_point=5000,integral=0,redpacket_amount=0,stat_total_amount=0,balance=0,frozen_amount=0,game_level=0,wrong_quantity=0,right_quantity=0 where id=0;
        // update yx_users set invite_quantity=0 where id=0;

        $userId = 0;
        $data = [
            'redpacket_amount' => Db::table(YxAnswersModel::TABLE_NAME)->where('user_id', $userId)->where('redpacket_amount', '>', 0)->sum('redpacket_amount'),
            'stat_total_amount' => 0,
            'wrong_quantity' => Db::table(YxAnswersModel::TABLE_NAME)->where('user_id', $userId)->where('status', 1)->count(),
            'right_quantity' => Db::table(YxAnswersModel::TABLE_NAME)->where('user_id', $userId)->where('status', 0)->count(),
            'invite_quantity' => Db::table(YxUsersModel::TABLE_NAME)->where('inviter_id', $userId)->count(),
        ];
    }

    /**
     * 返回排行榜
     */
    public static function getRankingList($type, $count = 50)
    {
        $cacheName = "ranking_of_users_{$type}_{$count}";
        $list = Cache::get($cacheName);
        if (!$list) {
            $orderFields = [
                'game' => 'game_level', // 闯关
                'score' => 'redpacket_amount', // 积分
                'invite' => 'invite_quantity', // 邀请
                'wrong' => 'wrong_quantity', // 错题
                'right' => 'right_quantity', // 对题
            ];
            $orderField = isset($orderFields[$type]) ? $orderFields[$type] : 'game_level';
            $list = Db::table(self::TABLE_NAME)->order($orderField . ' desc')->limit($count)->field("id, nick_name, avatar, {$orderField} as score")->select();
            Cache::set($cacheName, $list, 60);
        }
        return $list;
    }

    /**
     * 返回班级学生列表
     */
    public static function getStudentsList($roomId, $type, $count = 50)
    {
        $cacheName = "ranking_of_students_{$roomId}_{$type}_{$count}";
        $list = Cache::get($cacheName);
        if (!$list) {
            $orderFields = [
                'game' => 'game_level', // 闯关
                'score' => 'redpacket_amount', // 积分
                'invite' => 'invite_quantity', // 邀请
                'wrong' => 'wrong_quantity', // 错题
                'right' => 'right_quantity', // 对题
            ];
            $orderField = isset($orderFields[$type]) ? $orderFields[$type] : 'game_level';
            $list = Db::table('v_classroom2students')->where('room_id', $roomId)->order($orderField . ' desc')->limit($count)->field("id, nick_name, avatar, {$orderField} as score")->select();
            Cache::set($cacheName, $list, 60);
        }
        return $list;
    }

    /**
     * 获取分享列表
     */
    public static function getInvitesList($userId)
    {
        return Db::table(self::TABLE_NAME)->where('inviter_id', $userId)->field('id, nick_name, avatar')->select();
    }
}
